// Copyright Epic Games, Inc. All Rights Reserved.

#include "Cosmetics/LyraControllerComponent_CharacterParts.h"
#include "Cosmetics/LyraCharacterPartTypes.h"
#include "Cosmetics/LyraPawnComponent_CharacterParts.h"
#include "GameFramework/CheatManagerDefines.h"
#include "LyraCosmeticDeveloperSettings.h"
#include "GameFramework/Pawn.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraControllerComponent_CharacterParts)

//////////////////////////////////////////////////////////////////////

ULyraControllerComponent_CharacterParts::ULyraControllerComponent_CharacterParts(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

/**
 * 开始播放时调用
 */
void ULyraControllerComponent_CharacterParts::BeginPlay()
{
	Super::BeginPlay(); // 调用父类的BeginPlay

	// 监听Pawn占据改变事件
	if (HasAuthority()) // 如果有权限
	{
		if (AController* OwningController = GetController<AController>()) // 获取拥有控制器
		{
			OwningController->OnPossessedPawnChanged.AddDynamic(this, &ThisClass::OnPossessedPawnChanged); // 动态绑定到Pawn改变事件

			if (APawn* ControlledPawn = GetPawn<APawn>()) // 获取控制的Pawn
			{
				OnPossessedPawnChanged(nullptr, ControlledPawn); // 调用Pawn改变处理函数
			}
		}

		ApplyDeveloperSettings(); // 应用开发者设置
	}
}

/**
 * 结束播放时调用
 */
void ULyraControllerComponent_CharacterParts::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	RemoveAllCharacterParts(); // 移除所有角色部件
	Super::EndPlay(EndPlayReason); // 调用父类的EndPlay
}

/**
 * 获取Pawn定制器组件
 */
ULyraPawnComponent_CharacterParts* ULyraControllerComponent_CharacterParts::GetPawnCustomizer() const
{
	if (APawn* ControlledPawn = GetPawn<APawn>()) // 获取控制的Pawn
	{
		return ControlledPawn->FindComponentByClass<ULyraPawnComponent_CharacterParts>(); // 查找并返回角色部件组件
	}
	return nullptr; // 返回空指针
}

/**
 * 添加角色部件（公开接口）
 */
void ULyraControllerComponent_CharacterParts::AddCharacterPart(const FLyraCharacterPart& NewPart)
{
	AddCharacterPartInternal(NewPart, ECharacterPartSource::Natural); // 调用内部添加函数，标记为自然来源
}

/**
 * 内部添加角色部件函数
 */
void ULyraControllerComponent_CharacterParts::AddCharacterPartInternal(const FLyraCharacterPart& NewPart, ECharacterPartSource Source)
{
	FLyraControllerCharacterPartEntry& NewEntry = CharacterParts.AddDefaulted_GetRef(); // 在部件列表中添加新条目并获取引用
	NewEntry.Part = NewPart; // 设置部件数据
	NewEntry.Source = Source; // 设置部件来源

	if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) // 获取Pawn定制器
	{
		if (NewEntry.Source != ECharacterPartSource::NaturalSuppressedViaCheat) // 如果来源不是被抑制的自然部件
		{
			NewEntry.Handle = PawnCustomizer->AddCharacterPart(NewPart); // 通过定制器添加部件并获取句柄
		}
	}

}

/**
 * 移除指定的角色部件
 */
void ULyraControllerComponent_CharacterParts::RemoveCharacterPart(const FLyraCharacterPart& PartToRemove)
{
	for (auto EntryIt = CharacterParts.CreateIterator(); EntryIt; ++EntryIt) // 遍历部件条目迭代器
	{
		if (FLyraCharacterPart::AreEquivalentParts(EntryIt->Part, PartToRemove)) // 如果找到等效部件
		{
			if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) // 获取Pawn定制器
			{
				PawnCustomizer->RemoveCharacterPart(EntryIt->Handle); // 通过定制器移除部件
			}

			EntryIt.RemoveCurrent(); // 从列表中移除当前条目
			break; // 跳出循环
		}
	}
}

/**
 * 移除所有角色部件
 */
void ULyraControllerComponent_CharacterParts::RemoveAllCharacterParts()
{
	if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) // 获取Pawn定制器
	{
		for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) // 遍历所有部件条目
		{
			PawnCustomizer->RemoveCharacterPart(Entry.Handle); // 通过定制器移除部件
		}
	}

	CharacterParts.Reset(); // 重置部件列表
}

/**
 * 当控制的Pawn改变时调用
 */
void ULyraControllerComponent_CharacterParts::OnPossessedPawnChanged(APawn* OldPawn, APawn* NewPawn)
{
	// 从旧Pawn移除
	if (ULyraPawnComponent_CharacterParts* OldCustomizer = OldPawn ? OldPawn->FindComponentByClass<ULyraPawnComponent_CharacterParts>() : nullptr) // 获取旧Pawn的定制器
	{
		for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) // 遍历所有部件条目
		{
			OldCustomizer->RemoveCharacterPart(Entry.Handle); // 通过旧定制器移除部件
			Entry.Handle.Reset(); // 重置条目句柄
		}
	}

	// 应用到新Pawn
	if (ULyraPawnComponent_CharacterParts* NewCustomizer = NewPawn ? NewPawn->FindComponentByClass<ULyraPawnComponent_CharacterParts>() : nullptr) // 获取新Pawn的定制器
	{
		for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) // 遍历所有部件条目
		{
			// 如果句柄无效且来源不是被抑制的自然部件，则重新添加（当旧Pawn为空时可能被调用）
			if (!Entry.Handle.IsValid() && Entry.Source != ECharacterPartSource::NaturalSuppressedViaCheat)
			{
				Entry.Handle = NewCustomizer->AddCharacterPart(Entry.Part); // 通过新定制器添加部件并获取新句柄
			}
		}
	}
}

/**
 * 应用开发者设置
 */
void ULyraControllerComponent_CharacterParts::ApplyDeveloperSettings()
{
#if UE_WITH_CHEAT_MANAGER // 如果有作弊管理器
	const ULyraCosmeticDeveloperSettings* Settings = GetDefault<ULyraCosmeticDeveloperSettings>(); // 获取开发者设置默认对象

	// 如果需要，抑制或取消抑制自然部件
	const bool bSuppressNaturalParts = (Settings->CheatMode == ECosmeticCheatMode::ReplaceParts) && (Settings->CheatCosmeticCharacterParts.Num() > 0); // 判断是否需要抑制自然部件
	SetSuppressionOnNaturalParts(bSuppressNaturalParts); // 设置自然部件的抑制状态

	// 移除由开发者设置添加的任何内容并重新添加
	ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); // 获取Pawn定制器
	for (auto It = CharacterParts.CreateIterator(); It; ++It) // 遍历部件条目迭代器
	{
		if (It->Source == ECharacterPartSource::AppliedViaDeveloperSettingsCheat) // 如果来源是开发者设置作弊
		{
			if (PawnCustomizer != nullptr) // 如果定制器有效
			{
				PawnCustomizer->RemoveCharacterPart(It->Handle); // 通过定制器移除部件
			}
			It.RemoveCurrent(); // 从列表中移除当前条目
		}
	}

	// 添加新部件
	for (const FLyraCharacterPart& PartDesc : Settings->CheatCosmeticCharacterParts) // 遍历开发者设置中的作弊部件列表
	{
		AddCharacterPartInternal(PartDesc, ECharacterPartSource::AppliedViaDeveloperSettingsCheat); // 内部添加部件，标记为开发者设置来源
	}
#endif
}


/**
 * 添加作弊部件
 */
void ULyraControllerComponent_CharacterParts::AddCheatPart(const FLyraCharacterPart& NewPart, bool bSuppressNaturalParts)
{
#if UE_WITH_CHEAT_MANAGER // 如果有作弊管理器
	SetSuppressionOnNaturalParts(bSuppressNaturalParts); // 设置自然部件的抑制状态
	AddCharacterPartInternal(NewPart, ECharacterPartSource::AppliedViaCheatManager); // 内部添加部件，标记为作弊管理器来源
#endif
}

/**
 * 清除作弊部件
 */
void ULyraControllerComponent_CharacterParts::ClearCheatParts()
{
#if UE_WITH_CHEAT_MANAGER // 如果有作弊管理器
	ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); // 获取Pawn定制器

	// 移除由作弊管理器作弊添加的任何内容
	for (auto It = CharacterParts.CreateIterator(); It; ++It) // 遍历部件条目迭代器
	{
		if (It->Source == ECharacterPartSource::AppliedViaCheatManager) // 如果来源是作弊管理器
		{
			if (PawnCustomizer != nullptr) // 如果定制器有效
			{
				PawnCustomizer->RemoveCharacterPart(It->Handle); // 通过定制器移除部件
			}
			It.RemoveCurrent(); // 从列表中移除当前条目
		}
	}

	ApplyDeveloperSettings(); // 重新应用开发者设置
#endif
}

/**
 * 设置自然部件的抑制状态
 */
void ULyraControllerComponent_CharacterParts::SetSuppressionOnNaturalParts(bool bSuppressed)
{
#if UE_WITH_CHEAT_MANAGER // 如果有作弊管理器
	ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); // 获取Pawn定制器

	for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) // 遍历所有部件条目
	{
		if ((Entry.Source == ECharacterPartSource::Natural) && bSuppressed) // 如果是自然来源且需要抑制
		{
			// 抑制
			if (PawnCustomizer != nullptr) // 如果定制器有效
			{
				PawnCustomizer->RemoveCharacterPart(Entry.Handle); // 通过定制器移除部件
				Entry.Handle.Reset(); // 重置句柄
			}
			Entry.Source = ECharacterPartSource::NaturalSuppressedViaCheat; // 将来源标记为被抑制的自然部件
		}
		else if ((Entry.Source == ECharacterPartSource::NaturalSuppressedViaCheat) && !bSuppressed) // 如果是被抑制的自然来源且需要取消抑制
		{
			// 取消抑制
			if (PawnCustomizer != nullptr) // 如果定制器有效
			{
				Entry.Handle = PawnCustomizer->AddCharacterPart(Entry.Part); // 通过定制器重新添加部件并获取新句柄
			}
			Entry.Source = ECharacterPartSource::Natural; // 将来源标记为自然部件
		}
	}
#endif
}